/*
 * Copyright 2014 Semidata. All rights reserved.
 */
package com.semidata.rtd.engine.dynamic;

import java.io.StringWriter;
import java.lang.reflect.Method;
import java.util.Arrays;

import javax.tools.Diagnostic;
import javax.tools.DiagnosticCollector;
import javax.tools.JavaCompiler;
import javax.tools.JavaCompiler.CompilationTask;
import javax.tools.JavaFileObject;
import javax.tools.ToolProvider;

/**
 * @author shewei@semidata.com, She Wei
 * 
 */
public class DynamicCompiler {
	public static String message = "";
	
	

	public static Class<?> compile(DynamicClassLoader classLoader,
	        String className, String code) throws Exception {

		JavaCompiler javaCompiler = ToolProvider.getSystemJavaCompiler();
		MemoryFileManager fileManager = new MemoryFileManager(
		        javaCompiler.getStandardFileManager(null, null, null));

		JavaFileObject fileObject = new JavaSourceInMemory(className, code);
		DiagnosticCollector<JavaFileObject> diagnostics = new DiagnosticCollector<JavaFileObject>();
		StringWriter out = new StringWriter();
		CompilationTask task = javaCompiler.getTask(out, fileManager, diagnostics,
		        null, null, Arrays.asList(fileObject));

		if (!task.call()) {
			for (Diagnostic<? extends JavaFileObject> diagnostic : diagnostics.getDiagnostics()) {
                out.append("Error on line " + diagnostic.getLineNumber() + " in " + diagnostic).append('\n');
            }
			DynamicCompiler.message = out.toString(); 
			return null;
		} else {
			ClassObjectInMemory obj = fileManager.getClassObject();
			if (obj == null)
				return null;
			Class<?> clazz = classLoader.loadClass(className, obj);
			DynamicCompiler.message = out.toString();
			return clazz;
		}
	}

	public static void main(String[] args) {
//		Context context = new Context("arg1", "arg2", null);
//		String code = "package a.b.c;\nimport com.semidata.rtd.engine.dynamic.Context;\n" + "public class Test {\n"
//		        + "public static void meth(Context context) {\n"
//		        + "System.out.println(\"hello world\" + context.getArg3());\n" + "}\n}\n";
//		DynamicClassLoader loader = new DynamicClassLoader();
//		try {
//			Class<?> clazz = DynamicCompiler
//			        .compile(loader, "a.b.c.Test", code);
//			if (clazz == null) {
//				System.out.println(DynamicCompiler.message);
//				System.exit(-1);
//			}
//			System.out.println(DynamicCompiler.message);
//			System.out.println(clazz);
//			Method method = clazz.getDeclaredMethod("meth", Context.class);
//			method.invoke(null, context);
//		} catch (Exception e) {
//			e.printStackTrace();
//		}
	}

}
